package parser;

import java.util.ArrayList;

import exercicio.Lexer;
import exercicio.Token;
import exercicio.TokenType;


public class ParserTemp2 {

	private Lexer lexer;
	private Token currentToken;
	private int numTemp;
	private static int resposta = 0;
	private Token nextToken;
	private ArrayList exp = new ArrayList();
	private ArrayList chr = new ArrayList();
	private boolean flag = false;

	private void acceptToken(TokenType type) {
		if (currentToken.getToken() == type) {
			currentToken = lexer.nextToken();
		} else {
			throw new RuntimeException("Token inesperado. Foi lido um \""
					+ currentToken.getToken() + "\", quando o esperado era \""
					+ type + "\".");
		}
	}

	private void acceptToken() {
		currentToken = lexer.nextToken();
	}

	public void parse(String input) {
		lexer = new Lexer();
		lexer.reset(input);
		acceptToken();
		parseProgram();
	}

	private void parseProgram() {
		parseCommand();
	}

	private void parseCommand() {
		parseExpr();
		acceptToken(TokenType.PT_VIRG);
		resposta = operar(chr);
	}

	private void parseExpr() {
		parseTerm();
		parseRestExpr();
	}

	private void parseRestExpr() {			
		if (currentToken.getToken() == TokenType.ADD) {
			if(flag)
			{
				exp.add("+");
			}
			else
			{
				chr.add("+");
			}
			System.out.println("Leu adicao");
			acceptToken();
			parseTerm();
			parseRestExpr();
		} else {
			/* do nothing! */
		}
	}

	private void parseTerm() {
		parseFactor();
		parseRestTerm();
	}

	private void parseRestTerm() {
		if (currentToken.getToken() == TokenType.MULT) {
			if(flag)
			{
				exp.add("*");
			}
			else
			{
				chr.add("*");
			}
			System.out.println("Leu multplicacao");
			acceptToken();
			parseFactor();
			parseRestTerm();
		} else {
			/* do nothing! */
		}
	}

	private void parseFactor() {
		if (currentToken.getToken() == TokenType.NUMERO) {
			System.out.println("Leu numero "+ currentToken.getLexema());
			numTemp = Integer.parseInt(currentToken.getLexema());
			if (resposta == 0){
				numTemp = Integer.parseInt(currentToken.getLexema());
			} else{
				numTemp = resposta;
			}
			
			if(flag)
			{
				exp.add(currentToken.getLexema());
			}
			else
			{
				chr.add(currentToken.getLexema());
			}
			acceptToken();
		} else if (currentToken.getToken() == TokenType.ABRE_PAR) {
			System.out.println("Leu Abre Parenteses");
			flag = true;
			acceptToken();
			parseExpr();
			
			
			
			acceptToken(TokenType.FECHA_PAR);
			
			flag = false;
			System.out.println("Leu fecha parenteses");
			System.out.println("Parentesis "+exp);
			int x = operar(exp);
			chr.add(x);
			exp.clear();
			
			
		} else {
			throw new RuntimeException("Token inesperado: "
					+ currentToken.getToken() + ".");
		}
	}

	public static void main(String[] args) {
		String input = "(2*2+1)*2*2+5*2+5+2+8*(2*5)+(2+1);";
		ParserTemp2 parser = new ParserTemp2();
		System.out.println("Iniciou a analise sintatica");
		System.out.println(input);
		parser.parse(input);
		System.out.println("O resultado da expressao eh: " + resposta);
		System.out.println("Finalizou sem problemas!");
	}
	
	
	private int operar(ArrayList op)
	{
		int resultado = 0;
		int produto = 0;
		for (int i = 0; i < op.size(); i++) 
		{
			if (op.get(i) == "*")
			{
				produto = mult( Integer.parseInt(op.get(i-1).toString()), Integer.parseInt(op.get(i+1).toString()));
				op.remove(i+1);
				op.remove(i);
				op.add(i,produto);
				op.remove(i-1);
				i=0;
			}
		}
		int soma = 0;
			
		for (int i = 0; i < op.size(); i++) 
		{
			if (op.get(i) == "+")
			{
				soma = soma( Integer.parseInt(op.get(i-1).toString()), Integer.parseInt(op.get(i+1).toString()));
				op.remove(i+1);
				op.remove(i);
				op.add(i, soma);
				op.remove(i-1);
				i=0;
			}
		}
		resultado = Integer.parseInt(op.get(0).toString());
		
		return resultado;
	}
	
	private int mult(int op1, int op2) {
			int produto = op1 * op2;
			System.out.println("multiplicacao "+op1+" * "+op2+" = "+produto);
			return produto;
	}
	
	private int soma(int op1, int op2)
	{
		int soma = op1 + op2;
		System.out.println("soma "+op1+" + "+op2+" = "+soma);
		return soma;
	}
	
	
}
